﻿unit ProxyUtils;

interface

uses
  Windows, WinInet, IdURI, StrUtils, {RegularExpressions,} Classes, SysUtils, siAuto;


  function GetProxy(const URL: String; var ProxyServer: String; var ProxyPort: Integer): Boolean;

implementation

Type
  lpvoid  = pointer;

  PWINHTTP_CURRENT_USER_IE_PROXY_CONFIG = ^TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
  TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG = record
    fAutoDetect: BOOL;
    lpszAutoConfigUrl: LPWSTR;
    lpszProxy: LPWSTR;
    lpszProxyBypass: LPWSTR;
  end;
  PWINHTTP_AUTOPROXY_OPTIONS = ^TWINHTTP_AUTOPROXY_OPTIONS;
  TWINHTTP_AUTOPROXY_OPTIONS = record
    dwFlags: DWORD;
    dwAutoDetectFlags: DWORD;
    lpszAutoConfigUrl: LPCWSTR;
    lpvReserved: LPVOID;
    dwReserved: DWORD;
    fAutoLogonIfChallenged: BOOL;
  end;
  PWINHTTP_PROXY_INFO = ^TWINHTTP_PROXY_INFO;
  TWINHTTP_PROXY_INFO = record
    dwAccessType: DWORD;       // see WINHTTP_ACCESS_* types below
    lpszProxy: LPWSTR;         // proxy server list
    lpszProxyBypass: LPWSTR;   // proxy bypass list
  end;

const
// WinHttpOpen dwAccessType values (also for WINHTTP_PROXY_INFO::dwAccessType)
  WINHTTP_ACCESS_TYPE_DEFAULT_PROXY = 0;
  WINHTTP_ACCESS_TYPE_NO_PROXY = 1;
  WINHTTP_ACCESS_TYPE_NAMED_PROXY = 3;

// WinHttpOpen prettifiers for optional parameters
  WINHTTP_NO_PROXY_NAME = Nil;
  WINHTTP_NO_PROXY_BYPASS = Nil;

  WINHTTP_AUTOPROXY_AUTO_DETECT = $00000001;
  WINHTTP_AUTOPROXY_CONFIG_URL = $00000002;
  WINHTTP_AUTOPROXY_RUN_INPROCESS = $00010000;
  WINHTTP_AUTOPROXY_RUN_OUTPROCESS_ONLY = $00020000;
//
// Flags for dwAutoDetectFlags
//
  WINHTTP_AUTO_DETECT_TYPE_DHCP = $00000001;
  WINHTTP_AUTO_DETECT_TYPE_DNS_A = $00000002;

  function WinHttpOpen(pszAgentW: LPCWSTR; dwAccessType: DWORD;
    pszProxyW: LPCWSTR; pszProxyBypassW: LPCWSTR; dwFlags: DWORD): HINTERNET; stdcall; external 'Winhttp.dll';
  function WinHttpCloseHandle(hInternet: HINTERNET): Boolean; stdcall; external 'Winhttp.dll';
  function WinHttpGetProxyForUrl(hSession: HINTERNET; lpcwszUrl: LPCWSTR;
    pAutoProxyOptions: PWINHTTP_AUTOPROXY_OPTIONS; var pProxyInfo: TWINHTTP_PROXY_INFO): Boolean; stdcall; external 'Winhttp.dll';
  function WinHttpGetIEProxyConfigForCurrentUser(var pProxyConfig: TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG): Boolean; stdcall; external 'Winhttp.dll';



function GetProxy(const URL: String; var ProxyServer: String; var ProxyPort: Integer): Boolean;
var
  ProxyConfig: TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
  AutoProxyConfig: TWINHTTP_AUTOPROXY_OPTIONS;
  ProxyInfo: TWINHTTP_PROXY_INFO;

  ClnPos: Integer;
  hSession: HINTERNET;

  Proxy: String;
  ProxyBypass: String;

  Strs: TStrings;
  Idx: Integer;
  URI: TIdURI;
  Pattern: String;

  wURL:WideString;
begin
  ZeroMemory(@ProxyConfig, SizeOf(TWINHTTP_CURRENT_USER_IE_PROXY_CONFIG));
  
  WinHttpGetIEProxyConfigForCurrentUser(ProxyConfig);
  Proxy := '';
  wURL := URL;

  if ProxyConfig.fAutoDetect Or Assigned(ProxyConfig.lpszAutoConfigUrl) then
  begin
    hSession := WinHttpOpen(Nil, WINHTTP_ACCESS_TYPE_NO_PROXY,WINHTTP_NO_PROXY_NAME,WINHTTP_NO_PROXY_BYPASS,0);

    if not Assigned(hSession) then Exit;

    ZeroMemory(@AutoProxyConfig, SizeOf(TWINHTTP_AUTOPROXY_OPTIONS));
    
    if ProxyConfig.fAutoDetect then
    begin
      AutoProxyConfig.dwFlags := WINHTTP_AUTOPROXY_AUTO_DETECT;
      AutoProxyConfig.dwAutoDetectFlags := WINHTTP_AUTO_DETECT_TYPE_DHCP Or WINHTTP_AUTO_DETECT_TYPE_DNS_A;
    end else begin
      AutoProxyConfig.dwFlags := WINHTTP_AUTOPROXY_CONFIG_URL;
      AutoProxyConfig.dwAutoDetectFlags:=0;
      AutoProxyConfig.lpszAutoConfigUrl := ProxyConfig.lpszAutoConfigUrl;
      AutoProxyConfig.lpvReserved:=nil;
      AutoProxyConfig.dwReserved:=0;
      AutoProxyConfig.fAutoLogonIfChallenged:=false;
    end;

    wURL := URL;
    WinHttpGetProxyForUrl(hSession, pWideChar(wURL), @AutoProxyConfig, ProxyInfo);

    if Assigned(ProxyInfo.lpszProxy) then
    begin
      Proxy := ProxyInfo.lpszProxy;
      GlobalFree(Cardinal(ProxyInfo.lpszProxy));
    end;
    if Assigned(ProxyInfo.lpszProxyBypass) then
    begin
      ProxyBypass := ProxyInfo.lpszProxyBypass;
      GlobalFree(Cardinal(ProxyInfo.lpszProxyBypass));
    end;
    WinHttpCloseHandle(hSession);

  end
  else if Assigned(ProxyConfig.lpszProxy) then
  begin
    Proxy := ProxyConfig.lpszProxy;
    if Assigned(ProxyConfig.lpszProxyBypass) then
    begin
      ProxyBypass := ProxyConfig.lpszProxyBypass;
    end;
  end;

  if Proxy <> '' then
  begin
    ClnPos := Pos(':', Proxy);
    if ClnPos > 0 then
    begin
      ProxyServer := LeftStr(Proxy, ClnPos - 1);
      ProxyPort := StrToIntDef(RightStr(Proxy, Length(Proxy) - ClnPos), 0);
    end;

    siMain.LogString( 'aaa', ProxyBypass );

{    if ProxyBypass <> '' then
    begin
      URI := TIdURI.Create(URL);
      Strs := TStringList.Create;
      Strs.Delimiter := ';';
      Strs.DelimitedText := ProxyBypass;

      for Idx := 0 to Strs.Count - 1 do
      begin
        Pattern := Strs.Strings[Idx];
        Pattern := StringReplace(Pattern, '.', '\.', [rfReplaceAll]);
        Pattern := StringReplace(Pattern, '*', '.*', [rfReplaceAll]);

//        if TRegEx.IsMatch(URI.Host, Pattern) then
//        begin
//          ProxyServer := '';
//          ProxyPort := 0;
//          break;
//        end;
      end;
      FreeAndNil(URI);
    end;
}    
  end else begin
    ProxyServer := '';
    ProxyPort := 0;
  end;

  Result := (ProxyServer <> '');

  if Assigned(ProxyConfig.lpszAutoConfigUrl) then
    GlobalFree(Cardinal(ProxyConfig.lpszAutoConfigUrl));
  if Assigned(ProxyConfig.lpszProxy) then
    GlobalFree(Cardinal(ProxyConfig.lpszProxy));
  if Assigned(ProxyConfig.lpszProxyBypass) then
    GlobalFree(Cardinal(ProxyConfig.lpszProxyBypass));
end;


end.

